package utils.ai
{
	import global.GameType;
	
	import model.card.CardData;
	import model.card.ICardData;
	
	import utils.rule.IRuleResult;
	import utils.rule.RuleResult;

	public class CardTools
	{
		
		public static function getCardDataById(cardId:int):ICardData
		{		
			var cardValue:int = Math.floor(cardId / 4) + 3;
			var cardData:ICardData = getCardDataByIdAndValue(cardId,cardValue);
			return cardData;
		}
		
		public static function getCardDataByIdAndValue(cardId:int,cardValue:int):ICardData
		{
			var cardData:ICardData = new CardData();
			cardData.id = cardId;
			if (Math.floor(cardId / 4) + 3 > cardValue)
			{
				if ( cardId % 4 == 0 )
				{
					cardData.type = GameType.CARD_IMAGE_JOKER_BLACK;
					
				}
				else if (cardId % 4 == 1)
				{
					cardData.type = GameType.CARD_IMAGE_JOKER_RED;
				}
				cardData.value = GameType.CARD_VALUE_JOKER;
				cardData.jokerValue = cardValue;
			}
			else
			{
				if (Math.floor(cardId / 4) +3 > GameType.CARD_VALUE_2)
				{
					switch(cardId % 4)
					{
						case 0:
							cardData.type = GameType.CARD_IMAGE_JOKER_BLACK;
							break;
						case 1:
							cardData.type = GameType.CARD_IMAGE_JOKER_RED;
							break;
					}
				}
				else
				{
					switch (cardId % 4)
					{
						case 0:
							cardData.type = GameType.CARD_IMAGE_SPADES;
							break;
						case 1:
							cardData.type = GameType.CARD_IMAGE_HEARTS;
							break;
						case 2:
							cardData.type = GameType.CARD_IMAGE_CUBS;
							break;
						case 3:
							cardData.type = GameType.CARD_IMAGE_DIAMONS;
							break;
					}
				}
				cardData.value = cardValue;
			}
			
			return cardData;
		}
		
		public static function setGenerateBigPairStaright(generateCardDatas:Array,holdCardDatas:Array):Array
		{
			var result:Array = [];
			var generateCardData:ICardData;
			var cardData:ICardData;
			for (var i:int=0; i<generateCardDatas.length; i++)
			{
				generateCardData = generateCardDatas[i];
				var array:Array = getValueCard(generateCardData.value,holdCardDatas);
				var length:int = (array.length > 2)?2:array.length;
				for (var n:int=0; n<length;n++)
				{
					cardData = array[n];
					cardData = cardData.clone();
					result.push(cardData);
				}
				i++;
			}
			return result;
		}
		
		//检查持牌中是否含有该板凳对
		public static function checkBigPairStaright(generateCardDatas:Array,holdCardDatas:Array):Array
		{
			var gaps:Array = [];
			var generateCardData:ICardData;
			for (var i:int=0; i<generateCardDatas.length; i++)
			{
				generateCardData = generateCardDatas[i];
				if (getValueCard(generateCardData.value,holdCardDatas).length == 0)
				{
					return null;
				}
				else if (getValueCard(generateCardData.value,holdCardDatas).length == 1)
				{
					gaps.push(generateCardData);
					i++;
				}
				
			}
			return gaps;
		}
		
		//根据上一次出的牌生成可以打的对子
		public static function generateBigPairStraight(lastCardDatas:Array):Array
		{
			var result:Array = [];
			var cardData:ICardData;
			var newCardData:ICardData;
			for (var i:String in lastCardDatas)
			{
				cardData = lastCardDatas[i];
				newCardData = cardData.clone();
				newCardData.value = cardData.value + 1;
				if (newCardData.value > GameType.CARD_VALUE_A)
				{
					return result;
				}
				result.push(newCardData);
			}
			return result;
		}
		
		//取得所有的对子
		public static function getPairs(cardDatas:Array):Array
		{
			var result:Array = [];
			var pairOrBombs:Array = getAllPairOrBombs(cardDatas);
			for (var i:String in pairOrBombs)
			{
				if (pairOrBombs[i].length == 2)
				{
					result.push(pairOrBombs[i]);
				}
			}
			return result;
		}
		
		public static function combineJokerToBombs(joker:ICardData,rest:Array):Array
		{
			var pairOrBombs:Array = getAllPairOrBombs(rest);
			var combineAble:Array = [];
			var array:Array;
			for (var i:String in pairOrBombs)
			{
				array = pairOrBombs[i];
				if (array.length < 4)
				{
					joker = joker.clone();
					joker.jokerValue = array[0].value;
					array.push(joker);
					combineAble.push(CardTools.cloneCardDatas(array));
				}	
			}
			return combineAble;	
		}
		
		//取得所有的炸弹
		public static function getAllBombs(cardDataS:Array):Array
		{
			var result:Array = getAllPairOrBombs(cardDataS);
			var array:Array;
			var results:Array = [];
			for (var i:String in result)
			{
				array = result[i];
				if (array.length >= 3)
				{
					results.push(array);		
				}
			}
			return results;
		}
		
		//所有牌中取得对牌
		public static function getAllPairOrBombs(cardDataS:Array):Array
		{
			var result:Array = [];
			
			var cardData:ICardData;
			for (var i:String in cardDataS)
			{
				cardData = cardDataS[i];
				var array:Array = getValueCard(cardData.value,cardDataS);
				if (array.length >= 2)
				{
					pushHintResult(array.concat(),result);
					if (array.length == 3)
					{
						array.splice(0,1);
						pushHintResult(array.concat(),result);
					}
					else if (array.length == 4)
					{
						array.splice(0,1);
						pushHintResult(array.concat(),result);
						array.splice(0,1);
						pushHintResult(array.concat(),result);
					}
				}
			}
			return result;
		}
		
	
		//存放自动提示结果
		public static function pushHintResult(hint:Array,results:Array):void
		{
			var array:Array;
			sortCards(hint);
			for (var i:int=0; i<results.length; i++)
			{
				array = results[i];
				sortCards(array);
				if (array.length == hint.length)
				{
					for (var n:int=0; n<array.length; n++)
					{
						if (array[n].value != hint[n].value)
						{
							break;
						}
						
						if (n == array.length - 1)
						{
							return;
						}
					}
				}
			}
			
			results.push(hint);
		}
		
		
		//比较两个炸弹的大小
		public static function compairTwoBombs(bomb1:Array,bomb2:Array):Boolean
		{
			if (bomb1.length < 2)
			{
				return false;
			}
			
			if (bomb1.length == 2 && bomb1[0].value == GameType.CARD_VALUE_JOKER)
			{
				return true;
			} 
			
			if (bomb1.length > bomb2.length)
			{
				return true;
			}
			else if (bomb1.length == bomb2.length)
			{
				if (bomb1[0].value > bomb2[0].value)
				{
					return true;
				}
			}
			return false;
		}
		
		public static function setJokerPairStarightGap(joker:ICardData,rest:Array):Array
		{
			var results:Array = [];
			var ruleResult:IRuleResult = isPairStraight(rest);
			if (ruleResult.correct)
			{
				return results;
			}
			else
			{
				if (ruleResult.results.length == 1)
				{
					joker = joker.clone();
					joker.jokerValue = ruleResult.results[0].value;
					rest = CardTools.cloneCardDatas(rest);
					rest.push(joker);
					results.push(rest);
				}
			}
			return results;
		}
		
		//是否是连对
		public static function isPairStraight(cardDataS:Array):IRuleResult
		{
			var ruleResult:IRuleResult = new RuleResult();
			var results:Array = [];
			ruleResult.results = results;
			
			CardTools.sortCards(cardDataS);
			
			var difArray:Array = [];
			var lastCardData:ICardData;
			var currCardData:ICardData;
			for (var i:int=0; i<cardDataS.length; i++)
			{
				if (lastCardData == null)
				{
					lastCardData = cardDataS[i];
					difArray.push(lastCardData);
				}
				else
				{
					currCardData = cardDataS[i];
					if (lastCardData.value != currCardData.value)
					{
						difArray.push(currCardData);
					}
					lastCardData = currCardData;
				}
			}

			if (isCardDatasStraight(difArray))
			{
				for (var n:String in difArray)
				{
					currCardData = difArray[n];
					if (getValueCard(currCardData.value,cardDataS).length != 2)
					{
						results.push(currCardData.clone());
					}
				}
				
				if (results.length == 0)
				{
					ruleResult.correct = true;
				}
			}	
			
			return ruleResult;
		}
		
		//
		public static function getValueCard(value:int,cardDataS:Array):Array
		{
			var result:Array = [];
			var cardData:ICardData;
			for (var i:String in cardDataS)
			{
				cardData = cardDataS[i];
				if (cardData.value == value)
				{
					result.push(cardData);
				}
			}
			return result;
		}
		
		//检查王和其他排是否能组成连排
		public static function combineJokerWithRestToStraight(joker:ICardData,cardDataS:Array):Array
		{
			var result:Array = [];
			if (cardDataS.length < 2 || isCardDatasTheSame(cardDataS))
			{
				return result;
			}
			
			var gaps:Array = hasGap(cardDataS);
			if (gaps.length > 1)
			{
				return result;
			}
			else if (gaps.length == 1)
			{
				joker.jokerValue = gaps[0].value;
				result.push(cardDataS.concat(joker));
				return result;
			}
			else//0
			{
				var bigCardData:ICardData = cardDataS[0];
				if (bigCardData.value < GameType.CARD_VALUE_A)
				{
					joker = joker.clone();
					joker.jokerValue = bigCardData.value + 1;
					result.push(cardDataS.concat(joker));
				}
				
				var smallCardData:ICardData = cardDataS[cardDataS.length - 1];
				if (smallCardData.value > GameType.CARD_VALUE_3)
				{
					joker = joker.clone();
					joker.jokerValue = smallCardData.value - 1;
					result.push(cardDataS.concat(joker));
				}
			}
			
			var out:Array = [];
			
			for (var i:String in result)
			{
				sortCards(result[i]);
				if (isCardDatasStraight(result[i]))
				{
					out.push(result[i]);
				}
			}
			
			return out;
		}
		
		public static function hasGap(cardDataS:Array):Array
		{
			var results:Array = [];
			var lastCardData:ICardData;
			var currCardData:ICardData;
			var gapCardData:ICardData;
			for (var i:int = 0; i<cardDataS.length; i++)
			{
				if (lastCardData == null)
				{
					lastCardData = cardDataS[i];
				}
				else
				{
					currCardData = cardDataS[i];
					
					if (lastCardData.value > currCardData.value + 1)
					{
						for ( var n:int = currCardData.value + 1; n<lastCardData.value; n++)
						{
							gapCardData = new CardData();
							gapCardData.value = n;
							results.push(gapCardData);
						}
					}
				
					lastCardData = currCardData;
				}
			}
			
			return results;
		}
		
		
		//设置王和其他牌一样
		public static function setJokerAsOthers(joker:ICardData,cardDataS:Array):Array
		{
			var cardData:ICardData;
			cardDataS = cloneCardDatas(cardDataS);
			joker = joker.clone();
			for (var i:String in cardDataS)
			{
				cardData = cardDataS[i];
				joker.jokerValue = cardData.value;
				cardDataS.push(joker);
				return cardDataS;
			}
			return cardDataS;
		}
		
		//比较两张牌
		public static function compairTwoCards(cardData1:ICardData,cardData2:ICardData):Boolean
		{
			if (cardData1.value == GameType.CARD_VALUE_JOKER)
			{
				return false;
			}
			
			var result:Boolean;
			if (cardData1.value > cardData2.value)
			{
				if (cardData1.value == GameType.CARD_VALUE_2)
				{
					return true;
				}
				else if (cardData1.value == cardData2.value + 1)
				{
					return true;
				}
				return false;
			}
			else
			{
				return false;
			}
		}
		
		//克隆扑克
		public static function cloneCardDatas(cardDatas:Array):Array
		{
			if (cardDatas == null)
			{
				return null;
			}
			
			var clones:Array = [];
			var cardData:ICardData;
			for (var i:String in cardDatas)
			{
				cardData = cardDatas[i];
				clones.push(cardData.clone());	
			}
			
			return clones;
		}
		
		//检查所有的牌是不是连牌
		public static function isCardDatasStraight(cardDatas:Array):Boolean
		{
			if (cardDatas)
			{
				sortCards(cardDatas);
				var lastCardData:ICardData;
				var currentCardData:ICardData;
				for (var i:int = 0; i<cardDatas.length; i++)
				{
					if (lastCardData == null)
					{
						lastCardData = cardDatas[i];
					}
					else
					{
						currentCardData = cardDatas[i];
						if (currentCardData.value + 1 != lastCardData.value)
						{
							return false;
						}
						if (lastCardData.value > GameType.CARD_VALUE_A)
						{
							return false;
						}
						lastCardData = currentCardData;
						if (currentCardData.value < GameType.CARD_VALUE_3)
						{
							return false;
						}
						
						
					}
				}
				return true;
			}
			return false;
		}
		
		//检查所有的牌是不是一样的
		public static function isCardDatasTheSame(cardDatas:Array):Boolean
		{
			if (cardDatas)
			{
				var lastCardData:ICardData;
				var currentCardData:ICardData;
				for (var i:String in cardDatas)
				{
					if (lastCardData == null)
					{
						lastCardData = cardDatas[i];
					}
					else
					{
						currentCardData = cardDatas[i];
						if (currentCardData.value != lastCardData.value)
						{
							return false;
						}
					}
				}
				return true;
			}
			return false;
		}
		
		//取得除大小王剩下的牌
		public static function getRest(cardDatas:Array):Array
		{
			var result:Array = [];
			if (cardDatas)
			{
				var cardData:ICardData;
				for (var i:String  in cardDatas)
				{
					cardData = cardDatas[i];
					if (cardData.value != GameType.CARD_VALUE_JOKER)
					{
						result.push(cardData);
					}
				}
			}
			return result;	
		}
		
		//取得大小王
		public static function getJokers(cardDatas:Array,isResort:Boolean = true):Array
		{
			var result:Array = [];
			if (cardDatas)
			{
				if (isResort)
				{
					sortCards(cardDatas);
				}
				var cardData:ICardData;
				for (var i:String in cardDatas)
				{
					cardData = cardDatas[i];
					if (cardData.value == GameType.CARD_VALUE_JOKER)
					{
						result.push(cardData);
					}
				}
			}
			return result;
		}
		
		//扑克排序
		public static function sortCards(cardDatas:Array):Array
		{
			if (cardDatas)
			{
				cardDatas.sort(sortCompare);
			}
			return cardDatas;
		}
		
		private static function sortCompare(card1:*,card2:*):int
		{
			if (card1.value > card2.value)
			{
				return -1;
			}
			else if (card1.value < card2.value)
			{
				return 1;
			}
			else
			{
				if (card1.type < card2.type)
				{
					return -1;
				}
				else
				{
					return 1;
				}
			}
			
			return 1;
		}
	}
}